{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Introduction to atomman: ase and phonopy conversions\n",
    "__Lucas M. Hale__, [lucas.hale@nist.gov](mailto:lucas.hale@nist.gov?Subject=ipr-demo), _Materials Science and Engineering Division, NIST_.\n",
    "    \n",
    "[Disclaimers](http://www.nist.gov/public_affairs/disclaimer.cfm) "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. Introduction<a id='section1'></a>\n",
    "\n",
    "The Atomic Simulation Environment, [ase](https://wiki.fysik.dtu.dk/ase/) Python package, provides an alternative representation of atomic configurations in Python.  It has many built-in tools for analyzing crystal structures as well as methods designed to integrate simulators into their environment.  Atomic configurations are represented in ase by the ase.Atoms class.\n",
    "\n",
    "The [phonopy](https://atztogo.github.io/phonopy/) Python package is a common tool used to evaluate phonons for a given atomic configuration.  Atomic configurations are represented in phonopy by the phonopy.Atoms class, which is based on the ase.Atoms class.\n",
    "\n",
    "Atomman provides built-in conversions between these two packages to allow users the opportunity to take advantage of the unique features and calculation tools provided by the different packages.  As the Atoms classes for the two external packages are comparable, the 'ase_Atoms' and 'phonopy_Atoms' conversion styles in atomman only differ by which package's Atoms class is returned.\n",
    "\n",
    "Converting to the Atoms classes of the two packages requires that said package(s) be installed.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Library Imports**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "atomman version = 1.4.0\n",
      "Notebook executed on 2021-08-04\n"
     ]
    }
   ],
   "source": [
    "# Standard Python libraries\n",
    "import datetime\n",
    "\n",
    "# http://www.numpy.org/\n",
    "import numpy as np\n",
    "\n",
    "import atomman as am\n",
    "import atomman.unitconvert as uc\n",
    "\n",
    "# Show atomman version\n",
    "print('atomman version =', am.__version__)\n",
    "\n",
    "# Show date of Notebook execution\n",
    "print('Notebook executed on', datetime.date.today())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Generate test system information (CsCl)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "avect =  [ 3.200,  0.000,  0.000]\n",
      "bvect =  [ 0.000,  3.200,  0.000]\n",
      "cvect =  [ 0.000,  0.000,  3.200]\n",
      "origin = [ 0.000,  0.000,  0.000]\n",
      "natoms = 2\n",
      "natypes = 2\n",
      "symbols = ('Cs', 'Cl')\n",
      "pbc = [ True  True  True]\n",
      "per-atom properties = ['atype', 'pos', 'charge', 'stress']\n",
      "     id |   atype |  pos[0] |  pos[1] |  pos[2]\n",
      "      0 |       1 |   0.000 |   0.000 |   0.000\n",
      "      1 |       2 |   1.600 |   1.600 |   1.600\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>atype</th>\n",
       "      <th>pos[0]</th>\n",
       "      <th>pos[1]</th>\n",
       "      <th>pos[2]</th>\n",
       "      <th>charge</th>\n",
       "      <th>stress[0][0]</th>\n",
       "      <th>stress[0][1]</th>\n",
       "      <th>stress[0][2]</th>\n",
       "      <th>stress[1][0]</th>\n",
       "      <th>stress[1][1]</th>\n",
       "      <th>stress[1][2]</th>\n",
       "      <th>stress[2][0]</th>\n",
       "      <th>stress[2][1]</th>\n",
       "      <th>stress[2][2]</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>1</td>\n",
       "      <td>2</td>\n",
       "      <td>1.6</td>\n",
       "      <td>1.6</td>\n",
       "      <td>1.6</td>\n",
       "      <td>-1.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   atype  pos[0]  pos[1]  pos[2]  charge  stress[0][0]  stress[0][1]  \\\n",
       "0      1     0.0     0.0     0.0     1.0           0.0           0.0   \n",
       "1      2     1.6     1.6     1.6    -1.0           0.0           0.0   \n",
       "\n",
       "   stress[0][2]  stress[1][0]  stress[1][1]  stress[1][2]  stress[2][0]  \\\n",
       "0           0.0           0.0           0.0           0.0           0.0   \n",
       "1           0.0           0.0           0.0           0.0           0.0   \n",
       "\n",
       "   stress[2][1]  stress[2][2]  \n",
       "0           0.0           0.0  \n",
       "1           0.0           0.0  "
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Generate box\n",
    "alat = uc.set_in_units(3.2, 'angstrom')\n",
    "box = am.Box(a=alat, b=alat, c=alat)\n",
    "\n",
    "# Generate atoms with atype, pos, charge, and stress properties\n",
    "atype = [1, 2]\n",
    "pos = [[0,0,0], [0.5, 0.5, 0.5]]\n",
    "charge = uc.set_in_units([1, -1], 'e')\n",
    "stress = uc.set_in_units(np.zeros((2, 3, 3)), 'MPa')\n",
    "atoms = am.Atoms(pos=pos, atype=atype, charge=charge, stress=stress)\n",
    "\n",
    "# Build system from box and atoms, and scale atoms\n",
    "system = am.System(atoms=atoms, box=box, scale=True, symbols=['Cs', 'Cl'])\n",
    "\n",
    "# Print system information\n",
    "print(system)\n",
    "system.atoms_df()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. System.dump('ase_Atoms') and System.dump('phonopy_Atoms')<a id='section2'></a>\n",
    "\n",
    "Parameters\n",
    "\n",
    "- **symbols** (*tuple, optional*) List of the element symbols that correspond to the atom types.  If not given, will use system.symbols if set, otherwise no element content will be included.\n",
    "\n",
    "- **return_prop** (*bool, optional*) Indicates if the extra per-atom properties are to be returned in a dictionary.  Default value is False.\n",
    "\n",
    "Returns\n",
    "\n",
    "- **atoms**/**atoms** (*ase.Atoms*/*phonopy.Atoms*) The external package's representation of a collection of atoms.\n",
    "\n",
    "- **prop** (*dict*) Dictionary containing any extra per-atom properties to include. Returned if return_prop is True."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Convert the atomman.System to an ase.Atoms object"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'ase.atoms.Atoms'>\n",
      "Atoms(symbols='CsCl', pbc=True, cell=[3.2, 3.2, 3.2])\n"
     ]
    }
   ],
   "source": [
    "aseatoms, prop = system.dump('ase_Atoms', return_prop=True)\n",
    "print(type(aseatoms))\n",
    "print(aseatoms)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As the ase.Atoms object does not allow user-defined per-atom properties, the extra properties can be returned as a dictionary by setting return_prop = True"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'charge': array([ 1., -1.]), 'stress': array([[[0., 0., 0.],\n",
      "        [0., 0., 0.],\n",
      "        [0., 0., 0.]],\n",
      "\n",
      "       [[0., 0., 0.],\n",
      "        [0., 0., 0.],\n",
      "        [0., 0., 0.]]])}\n"
     ]
    }
   ],
   "source": [
    "print(prop)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "System.dump('phonopy_Atoms') behaves exactly the same except returns a phonopy.Atoms object instead."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'phonopy.structure.atoms.PhonopyAtoms'>\n",
      "lattice:\n",
      "- [     3.200000000000000,     0.000000000000000,     0.000000000000000 ] # a\n",
      "- [     0.000000000000000,     3.200000000000000,     0.000000000000000 ] # b\n",
      "- [     0.000000000000000,     0.000000000000000,     3.200000000000000 ] # c\n",
      "points:\n",
      "- symbol: Cs # 1\n",
      "  coordinates: [  0.000000000000000,  0.000000000000000,  0.000000000000000 ]\n",
      "  mass: 132.905452\n",
      "- symbol: Cl # 2\n",
      "  coordinates: [  0.500000000000000,  0.500000000000000,  0.500000000000000 ]\n",
      "  mass: 35.453000\n"
     ]
    }
   ],
   "source": [
    "phonopyatoms, prop = system.dump('phonopy_Atoms', return_prop=True)\n",
    "print(type(phonopyatoms))\n",
    "print(phonopyatoms)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3. atomman.load('ase_Atoms') and atomman.load('phonopy_Atoms')<a id='section3'></a>\n",
    "\n",
    "Parameters\n",
    "\n",
    "- **atoms** (*ase.Atoms or phonopy.Atoms*) The external package's representation of a collection of atoms.\n",
    "\n",
    "- **symbols** (*tuple, optional*) Allows the list of element symbols to be assigned during loading. Useful if the symbols for the model differ from the standard element tags.\n",
    "\n",
    "- **prop** (*dict, optional*) Dictionary containing any extra per-atom properties to include.\n",
    "        \n",
    "Returns\n",
    "\n",
    "- **system** (*atomman.System*) An atomman representation of a system."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Load the ase.Atoms object along with the property dictionary."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "avect =  [ 3.200,  0.000,  0.000]\n",
      "bvect =  [ 0.000,  3.200,  0.000]\n",
      "cvect =  [ 0.000,  0.000,  3.200]\n",
      "origin = [ 0.000,  0.000,  0.000]\n",
      "natoms = 2\n",
      "natypes = 2\n",
      "symbols = ('Cl', 'Cs')\n",
      "pbc = [ True  True  True]\n",
      "per-atom properties = ['atype', 'pos', 'charge', 'stress']\n",
      "     id |   atype |  pos[0] |  pos[1] |  pos[2]\n",
      "      0 |       2 |   0.000 |   0.000 |   0.000\n",
      "      1 |       1 |   1.600 |   1.600 |   1.600\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>atype</th>\n",
       "      <th>pos[0]</th>\n",
       "      <th>pos[1]</th>\n",
       "      <th>pos[2]</th>\n",
       "      <th>charge</th>\n",
       "      <th>stress[0][0]</th>\n",
       "      <th>stress[0][1]</th>\n",
       "      <th>stress[0][2]</th>\n",
       "      <th>stress[1][0]</th>\n",
       "      <th>stress[1][1]</th>\n",
       "      <th>stress[1][2]</th>\n",
       "      <th>stress[2][0]</th>\n",
       "      <th>stress[2][1]</th>\n",
       "      <th>stress[2][2]</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td>0</td>\n",
       "      <td>2</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>1.6</td>\n",
       "      <td>1.6</td>\n",
       "      <td>1.6</td>\n",
       "      <td>-1.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   atype  pos[0]  pos[1]  pos[2]  charge  stress[0][0]  stress[0][1]  \\\n",
       "0      2     0.0     0.0     0.0     1.0           0.0           0.0   \n",
       "1      1     1.6     1.6     1.6    -1.0           0.0           0.0   \n",
       "\n",
       "   stress[0][2]  stress[1][0]  stress[1][1]  stress[1][2]  stress[2][0]  \\\n",
       "0           0.0           0.0           0.0           0.0           0.0   \n",
       "1           0.0           0.0           0.0           0.0           0.0   \n",
       "\n",
       "   stress[2][1]  stress[2][2]  \n",
       "0           0.0           0.0  \n",
       "1           0.0           0.0  "
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "system = am.load('ase_Atoms', aseatoms, prop=prop)\n",
    "    \n",
    "print(system)\n",
    "system.atoms_df()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Load the phonopy.Atoms object along with the property dictionary."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "avect =  [ 3.200,  0.000,  0.000]\n",
      "bvect =  [ 0.000,  3.200,  0.000]\n",
      "cvect =  [ 0.000,  0.000,  3.200]\n",
      "origin = [ 0.000,  0.000,  0.000]\n",
      "natoms = 2\n",
      "natypes = 2\n",
      "symbols = ('Cl', 'Cs')\n",
      "pbc = [ True  True  True]\n",
      "per-atom properties = ['atype', 'pos', 'charge', 'stress']\n",
      "     id |   atype |  pos[0] |  pos[1] |  pos[2]\n",
      "      0 |       2 |   0.000 |   0.000 |   0.000\n",
      "      1 |       1 |   1.600 |   1.600 |   1.600\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>atype</th>\n",
       "      <th>pos[0]</th>\n",
       "      <th>pos[1]</th>\n",
       "      <th>pos[2]</th>\n",
       "      <th>charge</th>\n",
       "      <th>stress[0][0]</th>\n",
       "      <th>stress[0][1]</th>\n",
       "      <th>stress[0][2]</th>\n",
       "      <th>stress[1][0]</th>\n",
       "      <th>stress[1][1]</th>\n",
       "      <th>stress[1][2]</th>\n",
       "      <th>stress[2][0]</th>\n",
       "      <th>stress[2][1]</th>\n",
       "      <th>stress[2][2]</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td>0</td>\n",
       "      <td>2</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>1.6</td>\n",
       "      <td>1.6</td>\n",
       "      <td>1.6</td>\n",
       "      <td>-1.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   atype  pos[0]  pos[1]  pos[2]  charge  stress[0][0]  stress[0][1]  \\\n",
       "0      2     0.0     0.0     0.0     1.0           0.0           0.0   \n",
       "1      1     1.6     1.6     1.6    -1.0           0.0           0.0   \n",
       "\n",
       "   stress[0][2]  stress[1][0]  stress[1][1]  stress[1][2]  stress[2][0]  \\\n",
       "0           0.0           0.0           0.0           0.0           0.0   \n",
       "1           0.0           0.0           0.0           0.0           0.0   \n",
       "\n",
       "   stress[2][1]  stress[2][2]  \n",
       "0           0.0           0.0  \n",
       "1           0.0           0.0  "
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "system = am.load('phonopy_Atoms', phonopyatoms, prop=prop)\n",
    "    \n",
    "print(system)\n",
    "system.atoms_df()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
